package systeminfo

import (
	"fmt"
	"runtime"
	"time"

	"gitee.com/les49/esgo/constant"
	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/host"
	"github.com/shirou/gopsutil/mem"
)

type ServerData struct {
	MemAll         uint64  `json:"memAll"`
	MemFree        uint64  `json:"memFree"`
	MemUsed        uint64  `json:"memUsed"`
	MemUsedPercent float64 `json:"memUsedPercent"`

	CpuUsedPercent float64 `json:"cpuUsedPercent"`
	Arch           string  `json:"cpuArch"`
	CpuCores       uint32  `json:"cpuCores"`

	OS       string `json:"os"`
	HostName string `json:"hostName"`
	Platform string `json:"platform"`
}

type ServerInfo struct {
	MemAll         string `json:"memAll"`
	MemFree        string `json:"memFree"`
	MemUsed        string `json:"memUsed"`
	MemUsedPercent string `json:"memUsedPercent"`

	CpuUsedPercent string `json:"cpuUsedPercent"`
	Arch           string `json:"cpuArch"`
	CpuCores       uint32 `json:"cpuCores"`

	OS       string `json:"os"`
	HostName string `json:"hostName"`
	Platform string `json:"platform"`
}

func convertToByteString(val uint64) string {
	if val > 1024 {
		return fmt.Sprintf("%0.2f GB", (float64(val) / constant.BYTE_UNIT_GB))
	} else if val > constant.BYTE_UNIT_MB {
		return fmt.Sprintf("%0.2f MB", (float64(val) / constant.BYTE_UNIT_MB))
	} else if val > constant.BYTE_UNIT_KB {
		return fmt.Sprintf("%0.2f KB", (float64(val) / constant.BYTE_UNIT_KB))
	}
	return fmt.Sprintf("%d ", val)
}

func convertToPercentString(val float64) string {
	return fmt.Sprintf("%0.2f %%", val)
}

func GetMemAll() uint64 {
	memInfo, _ := mem.VirtualMemory()
	return memInfo.Total
}

func GetMemFree() uint64 {
	memInfo, _ := mem.VirtualMemory()
	return memInfo.Available
}

func GetMemUsed() uint64 {
	memInfo, _ := mem.VirtualMemory()
	return memInfo.Used
}

func GetMemUsedPercent() float64 {
	memInfo, _ := mem.VirtualMemory()
	return memInfo.UsedPercent
}

func GetCpuPrencent() float64 {
	percent, _ := cpu.Percent(time.Second, false)
	return percent[0]
}

func GetCpuArch() string {
	return runtime.GOARCH
}

func GetCpuCores() uint32 {
	return uint32(runtime.GOMAXPROCS(0))
}

func GetOSInfo() string {
	info, _ := host.Info()
	return info.OS
}

func GetPlatform() string {
	info, _ := host.Info()
	return info.Platform
}

func GetHostName() string {
	info, _ := host.Info()
	return info.Hostname
}

func ReadServerData() *ServerData {
	return &ServerData{
		MemAll:         GetMemAll(),
		MemFree:        GetMemFree(),
		MemUsed:        GetMemUsed(),
		MemUsedPercent: GetMemUsedPercent(),

		CpuUsedPercent: GetCpuPrencent(),
		Arch:           GetCpuArch(),
		CpuCores:       GetCpuCores(),

		OS:       GetOSInfo(),
		Platform: GetPlatform(),
		HostName: GetHostName(),
	}
}

func ReadServerInfo() *ServerInfo {
	return &ServerInfo{
		MemAll:         convertToByteString(GetMemAll()),
		MemFree:        convertToByteString(GetMemFree()),
		MemUsed:        convertToByteString(GetMemUsed()),
		MemUsedPercent: convertToPercentString(GetMemUsedPercent()),

		CpuUsedPercent: convertToPercentString(GetCpuPrencent()),
		Arch:           GetCpuArch(),
		CpuCores:       GetCpuCores(),

		OS:       GetOSInfo(),
		Platform: GetPlatform(),
		HostName: GetHostName(),
	}
}
